<!--
Copyright 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="ct-commit-list.html">
<link rel="import" href="ct-tree-list.html">

<script>
function CTFailureGroup(tree, data, category) {
  this.key = data.key;
  this.tree = tree;
  this.examineUrl = this.tree + '/failure/' + encodeURIComponent(this.key);
  this.data = data;
  var cTree = CTTreeList.getTree(tree);
  if (cTree) {
    this.data.bugLabels = cTree.bugLabels;
  }

  this._annotation = CTFailureGroup._mergeAnnotations(data.getAnnotations());
  this._originalCategory = category || 'default';
  this._computeProperties();
}

CTFailureGroup.prototype.snoozeUntil = function(time) {
  return this._annotate({
    snoozeTime: time,
  });
};

CTFailureGroup.prototype.unsnooze = function() {
  return this._annotate({
    snoozeTime: undefined,
  });
};

CTFailureGroup.prototype.setBug = function(bug) {
  if (/^[0-9]+$/.test(bug))
    bug = 'https://crbug.com/' + bug;
  return this._annotate({
    bug: bug,
  });
};

CTFailureGroup.prototype.clearBug = function() {
  return this._annotate({
    bug: undefined,
  });
};

CTFailureGroup.prototype._isTreeCloser = function() {
  return this.data.isTreeCloser && this.data.isTreeCloser();
}

CTFailureGroup.prototype._failedOnce = function() {
  return this.data.failedOnce && this.data.failedOnce();
}

CTFailureGroup.prototype._computeProperties = function() {
  this.isSnoozed = Date.now() < this._annotation.snoozeTime;
  if (this.isSnoozed) {
    this.category = 'snoozed';
  } else if (this._isTreeCloser()) {
    this.category = 'treeCloser';
  } else if (this._failedOnce()) {
    this.category = 'failedOnce';
  } else {
    this.category = this._originalCategory;
  }

  this.bug = this._annotation.bug;
  // FIXME: Bug labels would be simpler to implement as a filter in the UI.
  if (this.bug != null)
    this.bugLabel = 'Bug ' + /([0-9]{3,})/.exec(this.bug)[0];
  else
    this.bugLabel = undefined;
};

CTFailureGroup._mergeAnnotations = function(failureAnnotations) {
  // FIXME: This should be a union of all bugs.
  var bug = failureAnnotations.map('bug').compact().first();

  // The group is only snoozed if all the failures specify a snooze-time, and only
  // until the first has elapsed.
  var snoozeTimes = failureAnnotations.map('snoozeTime').compact();
  var snoozeTime = snoozeTimes.length < failureAnnotations.length ? undefined : snoozeTimes.min();

  var annotation = {};
  if (bug != null) {
    annotation.bug = bug;
  }
  if (snoozeTime != null) {
    annotation.snoozeTime = snoozeTime;
  }
  return annotation;
};

CTFailureGroup.prototype._annotate = function(newAnnotation) {
  var failureAnnotations = [];
  // FIXME: Post the new annotation to frontend rather than storing locally.
  return CTFailureGroup.fetchAnnotations().then(function(annotations) {
    this.data.failureKeys().forEach(function(failureKey) {
      var annotation = annotations[failureKey] || {};

      Object.keys(newAnnotation, function(key, value) {
        if (value === undefined) {
          delete annotation[key];
        } else {
          annotation[key] = value;
        }
      });

      if (Object.size(annotation) == 0) {
        delete annotations[failureKey];
      } else {
        annotations[failureKey] = annotation;
        failureAnnotations.push(annotation);
      }
    });

    localStorage.CTFailureGroupAnnotations = JSON.stringify(annotations);
    this._annotation = CTFailureGroup._mergeAnnotations(failureAnnotations);
    this._computeProperties();
  }.bind(this));
};

CTFailureGroup.fetchAnnotations = function() {
  // FIXME: Fetch annotations from frontend.
  var stored = localStorage.CTFailureGroupAnnotations;
  var annotations = stored ? JSON.parse(stored) : {};
  return Promise.resolve(annotations);
};
</script>
